const canvas = document.getElementById("puzzleCanvas");
const ctx = canvas.getContext("2d");
const img = new Image();
img.crossOrigin = "Anonymous"; // 添加跨域支持
// 使用更稳定的图片源
img.src = "https://picsum.photos/600";

// 游戏配置 - 所有难度使用不同数量的拼图块
const config = {
  easy: { piecesPerSide: 3 },      // 3x3=9块
  medium: { piecesPerSide: 4 },    // 4x4=16块
  hard: { piecesPerSide: 5 },      // 5x5=25块
};

// 游戏状态
let currentLevel = "easy"; // 默认初级
let pieces = [];
let draggingPiece = null;
let hintPiece = null;
let offsetX = 0, offsetY = 0;
let gameStarted = false;

// 区域定义
const puzzleArea = {
  x: 0,
  y: 0,
  width: 600,
  height: 600
};

const operationArea = {
  x: 620,
  y: 0,
  width: 340,
  height: 600
};

// 随机生成操作区内的位置
const randomPosition = () => {
  return {
    x: operationArea.x + Math.random() * (operationArea.width - 200),
    y: Math.random() * (operationArea.height - 200)
  };
};

// 生成拼图碎片的拼合点 - 使两个碎片之间能够锁定
function generateJigsaw(row, col, width, height, piecesPerSide) {
  const jigSize = Math.min(width, height) * 0.15; // 锯齿大小
  
  // 基础矩形
  const baseRect = [
    {x: 0, y: 0},             // 左上
    {x: width, y: 0},         // 右上
    {x: width, y: height},    // 右下
    {x: 0, y: height}         // 左下
  ];
  
  const result = [];
  
  // 为每条边添加锯齿
  for (let i = 0; i < 4; i++) {
    const p1 = baseRect[i];
    const p2 = baseRect[(i + 1) % 4];
    
    result.push({x: p1.x, y: p1.y});
    
    // 只在内部边缘添加锯齿（不是拼图的外边缘）
    if ((i === 0 && row > 0) ||                              // 上边，且不是第一行
        (i === 1 && col < piecesPerSide - 1) ||              // 右边，且不是最后一列
        (i === 2 && row < piecesPerSide - 1) ||              // 下边，且不是最后一行
        (i === 3 && col > 0)) {                              // 左边，且不是第一列
      
      // 在边的中点添加锯齿
      const midX = (p1.x + p2.x) / 2;
      const midY = (p1.y + p2.y) / 2;
      
      // 确定锯齿方向
      let perpX = 0, perpY = 0;
      
      if (i === 0 || i === 2) { // 上边或下边
        perpY = i === 0 ? -jigSize : jigSize;  // 上边凸起，下边凹陷
        if ((row + col) % 2 === 0) perpY = -perpY; // 交替锯齿方向
      } else { // 左边或右边
        perpX = i === 3 ? -jigSize : jigSize;  // 左边凸起，右边凹陷
        if ((row + col) % 2 === 1) perpX = -perpX; // 交替锯齿方向
      }
      
      // 添加锯齿点（3点组成圆滑锯齿）
      const ctrlDist = Math.min(width, height) * 0.1;
      result.push({x: (p1.x + midX) / 2 + perpX * 0.3, y: (p1.y + midY) / 2 + perpY * 0.3});
      result.push({x: midX + perpX, y: midY + perpY});
      result.push({x: (midX + p2.x) / 2 + perpX * 0.3, y: (midY + p2.y) / 2 + perpY * 0.3});
    }
  }
  
  return result;
}

// 判断点是否在多边形内
function isPointInPolygon(x, y, polygon, offsetX, offsetY) {
  let inside = false;
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    let xi = polygon[i].x + offsetX, yi = polygon[i].y + offsetY;
    let xj = polygon[j].x + offsetX, yj = polygon[j].y + offsetY;
    
    let intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
    if (intersect) inside = !inside;
  }
  return inside;
}

// 初始化拼图
function generatePieces() {
  console.log("生成拼图碎片，难度:", currentLevel);
  pieces = [];
  
  // 获取配置
  const piecesPerSide = config[currentLevel].piecesPerSide;
  const pieceWidth = puzzleArea.width / piecesPerSide;
  const pieceHeight = puzzleArea.height / piecesPerSide;
  
  // 生成所有碎片
  for (let row = 0; row < piecesPerSide; row++) {
    for (let col = 0; col < piecesPerSide; col++) {
      // 计算碎片在原图中的位置
      const x = col * pieceWidth;
      const y = row * pieceHeight;
      
      // 生成带锯齿的形状（确保能完美拼合）
      const shape = generateJigsaw(row, col, pieceWidth, pieceHeight, piecesPerSide);
      
      // 创建碎片对象
      const piece = {
        id: row * piecesPerSide + col,
        shape: shape,
        correctX: x,
        correctY: y,
        width: pieceWidth,
        height: pieceHeight,
        row: row,
        col: col,
        x: randomPosition().x,
        y: randomPosition().y,
        fixed: false
      };
      
      pieces.push(piece);
    }
  }
  
  // 打乱顺序
  pieces.sort(() => Math.random() - 0.5);
  console.log("生成的碎片:", pieces.length, "个");
  
  // 初始绘制
  drawPuzzle();
}

// 绘制拼图
function drawPuzzle() {
  // 确保图片已加载
  if (!img.complete) {
    console.log("图片尚未加载完成，稍后重试");
    requestAnimationFrame(drawPuzzle);
    return;
  }

  // 清空画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  
  // 绘制完整的原始图片作为背景（无论是否有固定碎片）
  ctx.drawImage(img, 0, 0, img.width, img.height, puzzleArea.x, puzzleArea.y, puzzleArea.width, puzzleArea.height);
  
  // 添加半透明遮罩，使背景图片变暗
  ctx.fillStyle = "rgba(0, 0, 0, 0.6)"; // 黑色遮罩，60%不透明度
  ctx.fillRect(puzzleArea.x, puzzleArea.y, puzzleArea.width, puzzleArea.height);
  
  // 绘制拼图区轮廓
  ctx.strokeStyle = "#aaa";
  ctx.lineWidth = 1;
  ctx.strokeRect(puzzleArea.x, puzzleArea.y, puzzleArea.width, puzzleArea.height);
  
  // 绘制操作区轮廓
  ctx.strokeStyle = "#aaa";
  ctx.lineWidth = 1;
  ctx.strokeRect(operationArea.x, operationArea.y, operationArea.width, operationArea.height);
  
  // 添加区域标签
  ctx.fillStyle = "#666";
  ctx.font = "14px Arial";
  ctx.fillText("拼图区域", puzzleArea.x + 10, puzzleArea.y + 20);
  ctx.fillText("操作区域", operationArea.x + 10, operationArea.y + 20);
  
  // 首先绘制所有已固定的碎片（在下层）
  pieces.forEach(piece => {
    if (piece.fixed) {
      drawFixedPiece(piece);
    }
  });
  
  // 然后绘制所有未固定的碎片（在上层）
  pieces.forEach(piece => {
    if (!piece.fixed) {
      drawFloatingPiece(piece);
    }
  });
}

// 绘制浮动（未固定）的碎片
function drawFloatingPiece(piece) {
  ctx.save();
  
  // 如果正在拖动且接近正确位置，显示吸附辅助线
  if (draggingPiece === piece) {
    const distanceThreshold = 60;
    const targetX = puzzleArea.x + piece.correctX;
    const targetY = puzzleArea.y + piece.correctY;
    
    if (Math.abs(piece.x - targetX) < distanceThreshold && 
        Math.abs(piece.y - targetY) < distanceThreshold) {
      // 绘制辅助线
      ctx.save();
      ctx.strokeStyle = "rgba(46, 125, 50, 0.6)";
      ctx.lineWidth = 2;
      ctx.setLineDash([5, 3]);
      
      // 绘制正确位置的轮廓
      ctx.beginPath();
      piece.shape.forEach((point, i) => {
        if (i === 0) ctx.moveTo(puzzleArea.x + piece.correctX + point.x, puzzleArea.y + piece.correctY + point.y);
        else ctx.lineTo(puzzleArea.x + piece.correctX + point.x, puzzleArea.y + piece.correctY + point.y);
      });
      ctx.closePath();
      ctx.stroke();
      
      ctx.restore();
    }
  }
  
  // 添加阴影效果
  ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
  ctx.shadowBlur = 5;
  ctx.shadowOffsetX = 2;
  ctx.shadowOffsetY = 2;
  
  // 创建碎片形状路径用于裁剪
  ctx.beginPath();
  piece.shape.forEach((point, i) => {
    if (i === 0) ctx.moveTo(piece.x + point.x, piece.y + point.y);
    else ctx.lineTo(piece.x + point.x, piece.y + point.y);
  });
  ctx.closePath();
  
  // 创建裁剪路径
  ctx.save();
  ctx.clip();
  
  // 缩放因子
  const scaleX = img.width / puzzleArea.width;
  const scaleY = img.height / puzzleArea.height;
  
  // 计算矩形边界，确保覆盖整个形状
  // 首先找到形状的边界框
  let minX = Infinity, minY = Infinity;
  let maxX = -Infinity, maxY = -Infinity;
  
  piece.shape.forEach(point => {
    minX = Math.min(minX, point.x);
    minY = Math.min(minY, point.y);
    maxX = Math.max(maxX, point.x);
    maxY = Math.max(maxY, point.y);
  });
  
  // 添加一些边距确保完全覆盖
  const margin = 2;
  minX -= margin;
  minY -= margin;
  maxX += margin;
  maxY += margin;
  
  // 计算要绘制的矩形尺寸
  const rectWidth = maxX - minX;
  const rectHeight = maxY - minY;
  
  // 计算图像源区域，包含可能超出基本格子的部分
  // 计算碎片在原图中的位置，考虑偏移
  const correctXWithOffset = piece.correctX + minX;
  const correctYWithOffset = piece.correctY + minY;
  
  // 计算在原图中对应的区域
  const sourceX = correctXWithOffset * scaleX;
  const sourceY = correctYWithOffset * scaleY;
  const sourceWidth = rectWidth * scaleX;
  const sourceHeight = rectHeight * scaleY;
  
  // 绘制相应区域的图像到碎片位置
  ctx.drawImage(
    img,
    sourceX, sourceY, sourceWidth, sourceHeight,
    piece.x + minX, piece.y + minY, rectWidth, rectHeight
  );
  
  ctx.restore();
  
  // 绘制边框
  ctx.strokeStyle = "#666";
  ctx.lineWidth = 1;
  ctx.stroke();
  
  // 绘制提示高亮
  if (hintPiece === piece) {
    // 高亮当前碎片
    ctx.strokeStyle = "yellow";
    ctx.lineWidth = 3;
    ctx.stroke();
    
    // 显示目标位置
    ctx.globalAlpha = 0.3;
    ctx.fillStyle = "lime";
    
    // 在正确位置绘制形状提示
    ctx.beginPath();
    piece.shape.forEach((point, i) => {
      if (i === 0) ctx.moveTo(puzzleArea.x + piece.correctX + point.x, puzzleArea.y + piece.correctY + point.y);
      else ctx.lineTo(puzzleArea.x + piece.correctX + point.x, puzzleArea.y + piece.correctY + point.y);
    });
    ctx.closePath();
    ctx.fill();
    
    ctx.globalAlpha = 1.0;
  }
  
  ctx.restore();
}

// 绘制已固定的碎片
function drawFixedPiece(piece) {
  ctx.save();
  
  // 定位到拼图区中的正确位置
  const pieceX = puzzleArea.x + piece.correctX;
  const pieceY = puzzleArea.y + piece.correctY;
  
  // 创建碎片路径用于裁剪
  ctx.beginPath();
  piece.shape.forEach((point, i) => {
    if (i === 0) ctx.moveTo(pieceX + point.x, pieceY + point.y);
    else ctx.lineTo(pieceX + point.x, pieceY + point.y);
  });
  ctx.closePath();
  
  // 创建裁剪路径
  ctx.clip();
  
  // 缩放因子
  const scaleX = img.width / puzzleArea.width;
  const scaleY = img.height / puzzleArea.height;
  
  // 计算矩形边界，确保覆盖整个形状
  // 首先找到形状的边界框
  let minX = Infinity, minY = Infinity;
  let maxX = -Infinity, maxY = -Infinity;
  
  piece.shape.forEach(point => {
    minX = Math.min(minX, point.x);
    minY = Math.min(minY, point.y);
    maxX = Math.max(maxX, point.x);
    maxY = Math.max(maxY, point.y);
  });
  
  // 添加一些边距确保完全覆盖
  const margin = 2;
  minX -= margin;
  minY -= margin;
  maxX += margin;
  maxY += margin;
  
  // 计算要绘制的矩形尺寸
  const rectWidth = maxX - minX;
  const rectHeight = maxY - minY;
  
  // 计算图像源区域，考虑锯齿形状可能超出基本格子的部分
  const sourceX = (piece.correctX + minX) * scaleX;
  const sourceY = (piece.correctY + minY) * scaleY;
  const sourceWidth = rectWidth * scaleX;
  const sourceHeight = rectHeight * scaleY;
  
  // 绘制相应区域的图像到碎片位置
  ctx.drawImage(
    img,
    sourceX, sourceY, sourceWidth, sourceHeight,
    pieceX + minX, pieceY + minY, rectWidth, rectHeight
  );
  
  // 绘制边框
  ctx.strokeStyle = "#388E3C";  // 绿色边框
  ctx.lineWidth = 1;
  ctx.stroke();
  
  ctx.restore();
}

// 检查点是否在碎片内
function isPointInPiece(x, y, piece) {
  return isPointInPolygon(x, y, piece.shape, piece.x, piece.y);
}

// 检查碎片是否在其正确位置附近
function isPieceNearCorrectPosition(piece) {
  const distanceThreshold = 60; // 吸附距离阈值
  
  const targetX = puzzleArea.x + piece.correctX;
  const targetY = puzzleArea.y + piece.correctY;
  
  return (
    Math.abs(piece.x - targetX) < distanceThreshold && 
    Math.abs(piece.y - targetY) < distanceThreshold
  );
}

// 初始化游戏
img.onload = () => {
  console.log("图片加载完成:", img.width, "x", img.height);
  
  // 设置canvas大小以适应拼图区和操作区
  canvas.width = puzzleArea.width + operationArea.width;
  canvas.height = Math.max(puzzleArea.height, operationArea.height);
  
  // 默认选中初级难度
  document.querySelector('.difficulty-btn[data-level="easy"]').classList.add('active');
  
  generatePieces();
  gameStarted = true;
  
  console.log("游戏已初始化，难度: " + currentLevel + "，碎片数量: ", pieces.length);
};

img.onerror = () => {
  console.error("图片加载失败");
  alert("图片加载失败，请检查网络连接或刷新页面重试。");
};

// 交互逻辑：鼠标拖动
canvas.addEventListener("mousedown", (e) => {
  if (!gameStarted) return;
  
  const rect = canvas.getBoundingClientRect();
  const mouseX = e.clientX - rect.left;
  const mouseY = e.clientY - rect.top;
  
  // 从上往下检查（这样可以选择最上面的碎片）
  for (let i = pieces.length - 1; i >= 0; i--) {
    const piece = pieces[i];
    
    if (!piece.fixed && isPointInPiece(mouseX, mouseY, piece)) {
      draggingPiece = piece;
      
      // 将当前碎片移到数组末尾（绘制时会显示在最上层）
      pieces.splice(i, 1);
      pieces.push(piece);
      
      // 记录偏移量
      offsetX = mouseX - piece.x;
      offsetY = mouseY - piece.y;
      
      break;
    }
  }
});

canvas.addEventListener("mousemove", (e) => {
  if (!draggingPiece) return;
  
  const rect = canvas.getBoundingClientRect();
  const mouseX = e.clientX - rect.left;
  const mouseY = e.clientY - rect.top;
  
  // 设置碎片位置
  draggingPiece.x = mouseX - offsetX;
  draggingPiece.y = mouseY - offsetY;
  
  // 添加磁性吸引效果，当非常接近时（30像素以内）轻微吸引向正确位置
  const closeThreshold = 30;
  
  const targetX = puzzleArea.x + draggingPiece.correctX;
  const targetY = puzzleArea.y + draggingPiece.correctY;
  
  if (Math.abs(draggingPiece.x - targetX) < closeThreshold && 
      Math.abs(draggingPiece.y - targetY) < closeThreshold) {
    // 计算距离正确位置的距离比例，越近吸引力越强
    const xDistance = targetX - draggingPiece.x;
    const yDistance = targetY - draggingPiece.y;
    const ratio = 0.2; // 吸引力强度系数
    
    // 应用吸引力
    draggingPiece.x += xDistance * ratio;
    draggingPiece.y += yDistance * ratio;
  }
  
  drawPuzzle();
});

canvas.addEventListener("mouseup", (e) => {
  if (!draggingPiece) return;
  
  // 检查是否放在拼图区域中
  const inPuzzleArea = (
    draggingPiece.x >= puzzleArea.x - 50 && 
    draggingPiece.y >= puzzleArea.y - 50 &&
    draggingPiece.x < puzzleArea.x + puzzleArea.width - 50 &&
    draggingPiece.y < puzzleArea.y + puzzleArea.height - 50
  );
  
  if (inPuzzleArea) {
    // 检查是否接近正确位置
    if (isPieceNearCorrectPosition(draggingPiece)) {
      // 吸附到正确位置
      draggingPiece.x = puzzleArea.x + draggingPiece.correctX;
      draggingPiece.y = puzzleArea.y + draggingPiece.correctY;
      draggingPiece.fixed = true;
      
      console.log(`碎片 ${draggingPiece.id} 放置在正确位置`);
    } else {
      // 如果在拼图区但不在正确位置，返回操作区
      Object.assign(draggingPiece, randomPosition());
    }
  } else {
    // 如果不在拼图区域，则回到操作区
    Object.assign(draggingPiece, randomPosition());
  }
  
  drawPuzzle();
  draggingPiece = null;
  
  // 检测是否完成拼图
  if (pieces.every(p => p.fixed)) {
    setTimeout(() => {
      alert(`恭喜你完成了${currentLevel === 'easy' ? '初级' : currentLevel === 'medium' ? '中级' : currentLevel === 'hard' ? '高级' : '不规则形状'}难度的拼图！🎉`);
    }, 300);
  }
});

// 触摸事件支持
canvas.addEventListener("touchstart", (e) => {
  e.preventDefault();
  const touch = e.touches[0];
  const mouseEvent = new MouseEvent("mousedown", {
    clientX: touch.clientX,
    clientY: touch.clientY
  });
  canvas.dispatchEvent(mouseEvent);
});

canvas.addEventListener("touchmove", (e) => {
  e.preventDefault();
  if (!draggingPiece) return;
  
  const touch = e.touches[0];
  const mouseEvent = new MouseEvent("mousemove", {
    clientX: touch.clientX,
    clientY: touch.clientY
  });
  canvas.dispatchEvent(mouseEvent);
});

canvas.addEventListener("touchend", (e) => {
  e.preventDefault();
  const mouseEvent = new MouseEvent("mouseup", {});
  canvas.dispatchEvent(mouseEvent);
});

// 提示功能
function showHint() {
  if (!gameStarted) return;
  
  // 找出未固定的碎片
  const unfixedPieces = pieces.filter(p => !p.fixed);
  
  if (unfixedPieces.length === 0) {
    alert("所有碎片已经完成！");
    return;
  }
  
  // 随机选择一个未固定的碎片作为提示
  hintPiece = unfixedPieces[Math.floor(Math.random() * unfixedPieces.length)];
  
  // 更新画面显示提示
  drawPuzzle();
  
  // 5秒后取消提示
  setTimeout(() => {
    hintPiece = null;
    drawPuzzle();
  }, 5000);
}

// 切换难度
function changeDifficulty(level) {
  currentLevel = level;
  
  // 更新按钮样式
  document.querySelectorAll('.difficulty-btn').forEach(btn => {
    if (btn.dataset.level === level) {
      btn.classList.add('active');
    } else {
      btn.classList.remove('active');
    }
  });
  
  // 重新生成拼图
  generatePieces();
  
  console.log(`难度已切换为 ${level}，碎片数量: ${pieces.length}`);
}

// 添加按钮点击事件监听
document.getElementById("hintButton").addEventListener("click", showHint);

// 添加难度按钮事件监听
document.querySelectorAll('.difficulty-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    changeDifficulty(btn.dataset.level);
  });
});

function drawPieceAtTarget(piece) {
    ctx.save();
    
    if (piece.isVoronoi) {
        // 关键修改：保持同一个坐标系下的对应关系
        // 移动到目标区域原点
        ctx.translate(puzzleArea.x, puzzleArea.y);
        
        // 设置裁剪路径，使用原始多边形坐标（相对于原图原点）
        ctx.beginPath();
        ctx.moveTo(piece.sourcePolygon[0][0], piece.sourcePolygon[0][1]);
        for(let i = 1; i < piece.sourcePolygon.length; i++) {
            ctx.lineTo(piece.sourcePolygon[i][0], piece.sourcePolygon[i][1]);
        }
        ctx.closePath();
        ctx.clip();
        
        // 绘制原图，位置保持与原图原点一致
        ctx.drawImage(image, 0, 0, puzzleWidth, puzzleHeight);
    } else {
        // 网格碎片逻辑保持不变
        // ...
    }
    
    ctx.restore();
}
